package com.zy.cat.service.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.taobao.api.internal.util.StringUtils;
import com.zy.cat.common.annotation.RedisEvicts;
import com.zy.cat.common.annotation.RedisEvicts.RedisEvict;
import com.zy.cat.common.config.Configs;
import com.zy.cat.common.utils.AesEncryptUtils;
import com.zy.cat.common.utils.CalculateUtil;
import com.zy.cat.common.utils.IpUtil;
import com.zy.cat.common.utils.TJKUtils;
import com.zy.cat.common.utils.WeChatUtil;
import com.zy.cat.common.utils.push.PushClient;
import com.zy.cat.common.utils.push.UmengPushAPI;
import com.zy.cat.dao.Dao;
import com.zy.cat.entity.app.CatUserFeedbackHistory;
import com.zy.cat.entity.app.repository.CatUserFeedbackHistoryRepository;
import com.zy.cat.entity.dev.CatDevDeviceToken;
import com.zy.cat.entity.dev.CatDevUserInfo;
import com.zy.cat.entity.dev.act.CatDailyDrawHistory;
import com.zy.cat.entity.dev.act.CatDailyDrawPrizeInfo;
import com.zy.cat.entity.dev.act.CatDailyDrawResult;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawHistoryRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawPrizeInfoRepository;
import com.zy.cat.entity.dev.act.repository.CatDailyDrawResultRepository;
import com.zy.cat.entity.dev.act.resp.CatDailyDrawDetailResp;
import com.zy.cat.entity.dev.repository.CatDevDeviceTokenRepository;
import com.zy.cat.entity.dev.repository.CatDevNewAddOrderHistoryRepository;
import com.zy.cat.entity.game.CVSDrawHistory;
import com.zy.cat.entity.game.CVSInfo;
import com.zy.cat.entity.game.CardDrawCountHistory;
import com.zy.cat.entity.game.CardDrawHistory;
import com.zy.cat.entity.game.CardInfo;
import com.zy.cat.entity.game.TrunDrawCountHistory;
import com.zy.cat.entity.game.TrunDrawExtraRewardInfo;
import com.zy.cat.entity.game.TrunInfo;
import com.zy.cat.entity.game.repository.CVSInfoRepository;
import com.zy.cat.entity.game.repository.CardDrawCountHistoryRepository;
import com.zy.cat.entity.game.repository.CardInfoRepository;
import com.zy.cat.entity.game.repository.TrunInfoRepository;
import com.zy.cat.entity.game.resp.CVSInfoResp;
import com.zy.cat.entity.game.resp.CardInfoResp;
import com.zy.cat.entity.game.resp.Prize;
import com.zy.cat.entity.mall.CatGoodsCouponHistory;
import com.zy.cat.entity.mall.CatGoodsSubsidyHistory;
import com.zy.cat.entity.mall.TKTLJGoodsOrders;
import com.zy.cat.entity.mall.repository.CatGoodsCouponHistoryRepository;
import com.zy.cat.entity.mall.repository.CatGoodsSubsidyHistoryRepository;
import com.zy.cat.entity.mall.repository.TKTLJGoodsOrdersRepository;
import com.zy.cat.entity.mall.resp.TKTLJGoodsResp;
import com.zy.cat.entity.wx.WxUserInfo;
import com.zy.cat.entity.wx.repository.WxUserInfoRepository;
import com.zy.cat.entity.wy.TKConvertResp;
import com.zy.cat.service.AsyncService;
import com.zy.cat.service.CacheService;
import com.zy.cat.service.CatDevService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
/**
 * 
 * @info 
 * @author Link
 * @date 2019-11-26 13:37
 */
public class AsyncServiceImpl implements AsyncService {
	@Autowired
	Dao<CatDevUserInfo> catdao;

	@Autowired
	Dao<CVSInfoResp> cvsinfodao;

	@Autowired
	Dao<CVSDrawHistory> cddao;
	
	@Autowired
	Dao<CardDrawHistory> cardDao;
	
	@Autowired
	Dao<CardDrawCountHistory> cardDrawCountHistoryDao;
	
	@Autowired
	Dao<CardInfoResp> cardInfoRespDao;
	
	@Autowired
	CardDrawCountHistoryRepository cardDrawCountHistoryRepository;
	
	@Autowired
	CatDevNewAddOrderHistoryRepository newAddOrderHistoryRepository;
	
	@Autowired
	CatUserFeedbackHistoryRepository userFeedbackHistoryRepository;
	
	@Autowired
	CatDailyDrawPrizeInfoRepository dailyDrawPrizeInfoRepository;
	
	@Autowired
	CatDailyDrawResultRepository dailyDrawResultRepository;

	@Autowired
	CVSInfoRepository cvsInfoRepository;
	
	@Autowired
	Dao<TrunInfo> trunInfoDao;
	
	@Autowired
	Dao<TKTLJGoodsResp> gDao;
	
	
	@Autowired
	Dao<TrunDrawCountHistory> trunDrawCountDao;
	
	@Autowired
	Dao<CatGoodsCouponHistory> catGoodsCouponHistoryDao;
	
	@Autowired
	Dao<CatDailyDrawDetailResp> dailyDrawDetailRespDao;
	
	@Autowired
	Dao<String> stringDao;
	
	@Autowired
	Dao<CatDailyDrawPrizeInfo> dailyDrawPrizeInfoDao;
	
	@Autowired
	Dao<CatDevDeviceToken> catDevDeviceToken;
	
	@Autowired
	Dao<TrunDrawExtraRewardInfo> trunExtraRewardDao;
	
	@Autowired
	TrunInfoRepository trunInfoRepository;
	
	@Autowired
	CardInfoRepository cardInfoRepository;
	
	@Autowired
	CatGoodsSubsidyHistoryRepository catGoodsSubsidyHistoryRepository;
	
	@Autowired
	CatGoodsCouponHistoryRepository catGoodsCouponHistoryRepository;
	
	@Autowired
	CatDailyDrawHistoryRepository dailyDrawHistoryRepository;
	
	@Autowired
	CatDevDeviceTokenRepository catDevDeviceTokenRepository;
	
	
	@Autowired
	WxUserInfoRepository wxUserInfoRepository;
	
	@Autowired
	CacheService cacheService;
	
	@Autowired
	CatDevService catDevService;
	
	@Autowired
	Configs configs;
	
	@Autowired
	@Qualifier("redis0")
	RedisTemplate<String, Object> redis0;
	
	@Autowired
	@Qualifier("redis15")
	RedisTemplate<String, Object> redis15;
	
	@Autowired
	@Qualifier("redis11")
	RedisTemplate<String, Object> redis11;
	
	
	@Autowired
	TKTLJGoodsOrdersRepository tKTLJGoodsOrdersRepository;

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void updateCatDevWeInfo(String unionid,String openid) {
		CatDevUserInfo userInfo = new CatDevUserInfo();
		userInfo.setUnionid(unionid);
		userInfo.setOpenid(openid);;
		if (catdao.update(userInfo, "updateWeInfo")) {
			log.info("执行异步任务->【修改9趣猫用户微信信息】成功");
		} else {
			log.info("执行异步任务->【修改9趣猫用户微信信息】失败");
		}
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void insertCVSGameInfo(int rtype, String pid) {
		CVSDrawHistory queryObj = new CVSDrawHistory(pid);
		queryObj.setDstatus(1);
		CVSDrawHistory timeInfo = cddao.selectOne(queryObj, "getTodayTimeInfo");
		String stime, etime;
		/* 最近中奖信息为空 */
		if (timeInfo == null) {
			stime = LocalDate.now().toString();
			etime = LocalDate.now().plusDays(6).toString();
		} else {
			/* 结束时间是否超过今天 */
			if (TJKUtils.parse2LocalDate(timeInfo.getEtime()).isAfter(LocalDate.now())) {
				stime = timeInfo.getStime();
				etime = timeInfo.getEtime();
			} else {
				stime = LocalDate.now().toString();
				etime = LocalDate.now().plusDays(6).toString();
			}
		}

		CVSInfoResp cvsInfoResp = cvsinfodao.selectOne(new CVSInfoResp(pid, stime, etime), "getCVSInfo");
		if (cvsInfoResp != null) {
			cvsInfoResp.setStime(stime);
			cvsInfoResp.setEtime(etime);
			if (cvsInfoRepository.saveAndFlush(new CVSInfo(cvsInfoResp)) != null) {
				log.info("执行异步任务->【记录每日神奇便利店抽奖信息】成功");
			} else {
				log.info("执行异步任务->【记录每日神奇便利店抽奖信息】失败");
			}
		} else {
			log.info("执行异步任务->【记录每日神奇便利店抽奖信息】失败");
		}

	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void insertTrunDrawInfo(int rtype, String pid) {
		//查询今日剩余大转盘抽奖次数
		TrunDrawCountHistory drawCountHistory = trunDrawCountDao.selectOne(new TrunDrawCountHistory(pid), "getTodayDrawsNum");
		TrunInfo trunInfo = trunInfoDao.selectOne(new TrunInfo(pid), "getTodayTrunInfo");
		//如果今天还未有记录则新建
		if (trunInfo==null) {
			trunInfo=new TrunInfo(pid, 0, 0, 0, 0, 0, 0);
		}
		if (drawCountHistory!=null) {
			trunInfo.setDcount(100-drawCountHistory.getDcount());
		}
		
		trunInfo.setPid(pid);
		trunInfo.setCtime(LocalDate.now().toString());
		//设置更新时间
		trunInfo.setLtime(TJKUtils.DateTime());
		//保存更新纪录
		if (trunInfoRepository.saveAndFlush(trunInfo) != null) {
			log.info("执行异步任务->【记录每日大转盘抽奖信息】成功");
		} else {
			log.info("执行异步任务->【记录每日大转盘抽奖信息】失败");
		}
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void insertCardGameInfo(int rtype, String pid) {
		//查询今日剩余卡数
		CardDrawCountHistory countHistory = cardDrawCountHistoryDao.selectOne(new CardDrawCountHistory(pid), "getLastCards");
		//查询500、1000、1500剩余次数
		CardInfoResp cardInfoResp=cardInfoRespDao.selectOne(new CardInfoResp(pid), "getCardInfo");
		CardInfoResp infoResp = cardInfoRespDao.selectOne(new CardInfoResp(pid), "getCardTodayBeanNum");
		//今日刮卡次数
		CardDrawCountHistory result_0=cardDrawCountHistoryRepository.findByPidAndCtimeAndDtype(pid, LocalDate.now().toString(), -1);
		//查询今日数据
		CardInfo cardInfo = cardInfoRepository.findByPidAndCtime(pid, TJKUtils.DateTime(TJKUtils.YYYY_MM_DD));
		//判断今日是都已经有记录
		if (cardInfo==null) {
			cardInfo=new CardInfo(pid, TJKUtils.DateTime(TJKUtils.YYYY_MM_DD), 0, 0, 0, 0, 0, 0, TJKUtils.DateTime());
		}
		cardInfo.setCard500(cardInfoResp.getCard500());
		cardInfo.setCard1000(cardInfoResp.getCard1000());
		cardInfo.setCard1500(cardInfoResp.getCard1500());
		cardInfo.setCards(countHistory.getDcount());
		//获取金豆数
		cardInfo.setBeans(infoResp.getBeans());
		cardInfo.setGcards(result_0==null?0:result_0.getDcount());
		cardInfo.setLtime(TJKUtils.DateTime());

		if (cardInfoRepository.saveAndFlush(cardInfo) != null) {
			log.info("执行异步任务->【记录每日刮刮卡抽奖信息】成功");
		} else {
			log.info("执行异步任务->【记录每日刮刮卡抽奖信息】失败");
		}
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void setGoodsSubsidyHistory(int rtype,int ftype,String pid, String rid, String sid, long fcode) {
		catGoodsSubsidyHistoryRepository.saveAndFlush(new CatGoodsSubsidyHistory(pid,ftype, sid, fcode, rid, TJKUtils.DateTime(), 0, TJKUtils.DateTime()));
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void setGoodsCouponHistory(int ftype, String pid, TKConvertResp tkConvert) {
		if (tkConvert.getError()==404 || tkConvert.getData()==null) {
			return;
		}
		CatGoodsCouponHistory object = JSON.parseObject(JSON.toJSONString(tkConvert.getData()), CatGoodsCouponHistory.class);
		object.setPid(pid);
		object.setCtime(TJKUtils.DateTime());
		object.setLtime(TJKUtils.DateTime());
		
		//保存
		catGoodsCouponHistoryRepository.saveAndFlush(object);
		
		//每个用户优惠券信息只存十条记录
		catGoodsCouponHistoryDao.delete(new CatGoodsCouponHistory(), "deleteLatTen");
		
//		String key="CAT_DEV_COUPON_COUNT";
//		//缓存中增加一条优惠券记录
//		if (redis0.hasKey(key) || !redis0.opsForHash().hasKey(key, pid)) {
//			redis0.opsForHash().put(key, pid, 1);
//		}else {
//			redis0.opsForHash().put(key, pid, (Integer)redis0.opsForHash().get(key, pid)+1);
//		}
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void templateMSG(String access_token,String touser, String url,List<String> datas,String template_id) {
		 if(url==null) {
			 url="";
		 }
		if(StringUtils.areNotEmpty(access_token,touser,template_id)) {
			WeChatUtil.sendTemplateMsg(access_token, touser, template_id, url, datas);
		}else {
			log.error("发送微信消息错误------------->");
			log.error("发送微信消息错误--access_token-->{}",access_token);
			log.error("发送微信消息错误--touser-->{}",touser);
			log.error("发送微信消息错误--url-->{}",url);
			log.error("发送微信消息错误--datas-->{}",JSON.toJSONString(datas));
		}
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void updateCatDevInviteAwardRecord(String pid,int type,long amount,String name,int index) {
		//获取用户Unionid
		CatDevUserInfo userInfo = catDevService.getCatDevUserInfoByPid(pid);
		//获取用户微信公众号openId
		WxUserInfo wxUserInfo = wxUserInfoRepository.findByUnionid(userInfo.getUnionid());
		if (wxUserInfo==null) {
			return;
		}
		String openid = wxUserInfo.getOpenid();
		String key="CAT_DEV_INVITE_AWARD_RECORD";

		Boolean isExist = redis15.opsForHash().hasKey(key, openid);
		//如果已存在记录,且操作类型为删除
		if (isExist && type==0) {
			//删除openid对应的记录
			redis15.opsForHash().delete(key, openid);
		}else if(!isExist && type==1){
			//操作类型为新增,且缓存中没有则插入
			redis15.opsForHash().put(key, openid, TJKUtils.DateTime());
		}
		//如果index为0则不用通知
		if (index==0) {
			return;
		}

		//发送通知
		String accessToken = cacheService.getWechatAccessToken(configs.getWxAppid(),configs.getWxSecret());
		String tid="UfhUPGoSxUb8MeE0A_qPE58lTtZlEBv_HR5sbxKgUYc";
//		String url="https://engine.seefarger.com/index/activity?appKey=4TFNJ2PU614pNANuW3wWuZjhgarN&adslotId=324201";
		String url="";
		String[] taskArray= {"注册成功","第二天打开APP","第三天打开APP","购物奖励金"};
		/*
    	邀新奖励入账通知
		入账金额：实际到账金额
		入账时间：实际到账日期
		入账类型：邀请好友奖励
		入账详情：被邀请好友状态，包含（1，xxx注册成功。2，xxx第二天打开APP。3xxx第三天打开APP。4，xxx购物奖励金）xxx为被邀请人微信名称
		感谢您的使用
    	*/
    	List<String> datas=new ArrayList<String>();
    	datas.add("邀新奖励入账通知");//例子中第一条
    	datas.add((amount/100.0)+"元");
    	datas.add(TJKUtils.DateTime());
    	datas.add("邀请好友奖励");
    	datas.add(AesEncryptUtils.decrypt(name)+taskArray[index-1]);
    	datas.add("感谢您的使用！");
		if(StringUtils.areNotEmpty(accessToken,openid,tid)) {
			WeChatUtil.sendTemplateMsg(accessToken, openid, tid, url, datas);
		}else {
			log.error("发送微信消息错误------------->");
			log.error("发送微信消息错误--access_token-->{}",accessToken);
			log.error("发送微信消息错误--touser-->{}",userInfo.getOpenid());
			log.error("发送微信消息错误--url-->{}",url);
			log.error("发送微信消息错误--datas-->{}",JSON.toJSONString(datas));
		}
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void insertLoginIp(HttpServletRequest request,String pid) {
		String key="IOS_LOGIN_IP_LOG";
		Map<String,String> dataMap=new HashMap<String, String>();
		//获取IP地址
		String ipAddr = IpUtil.getIpAddr(request);
		dataMap.put("time", TJKUtils.DateTime());
		dataMap.put("ip", ipAddr);
		dataMap.put("pid", pid);
		redis15.opsForList().leftPush(key, dataMap);
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	@RedisEvicts(before = false, evict = { @RedisEvict(rtype = 2, db = 13, key = "CAT_DEV_INFO", hashKeys = {"+#pid" }) })
	public void updateCatDevUtype(String pid, int utype) {
		CatDevUserInfo userInfo = new CatDevUserInfo();
		userInfo.setPid(pid);
		userInfo.setUtype(utype);
		if (catdao.update(userInfo, "updateUtype")) {
			log.info("执行异步任务->【修改9趣猫用户类型信息】成功");
		} else {
			log.info("执行异步任务->【修改9趣猫用户类型信息】失败");
		}
	}
	
	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void deleteNewAddOrderHistory(String pid) {
		newAddOrderHistoryRepository.deleteByPid(pid);
	}

	@Override
	public void insertTLJGoodsInfo(TKTLJGoodsOrders tktljGoodsOrders) {
		tktljGoodsOrders.setCtime(TJKUtils.DateTime());
		tktljGoodsOrders.setLtime(TJKUtils.DateTime());
		tktljGoodsOrders.setInfo("高佣转链,待领取");
		tKTLJGoodsOrdersRepository.saveAndFlush(tktljGoodsOrders);
	}

	@Override
	public void offLineTLJGoods(String sid, String info) {
		if(gDao.update(new TKTLJGoodsResp(sid,info))) {
			redis11.delete("CAT_TLJ_GOODS");
		}
	}

	@Override
	public void setTLJViewTime(String pid) {
		catdao.update(new CatDevUserInfo(pid), "updTljInfo");
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	public void updateFeedbackHistory(Integer appId, String userid) {
		List<CatUserFeedbackHistory> list = userFeedbackHistoryRepository.findByUserIdAndAppIdAndStatus(userid, appId,2);
		if (list==null) {
			return;
		}
		list.forEach(obj->{
			obj.setStatus(3);
			obj.setUpdateTime(new Date());
		});
		userFeedbackHistoryRepository.saveAll(list);
	}

	@Override
	@Async("zyasyncPoolTaskExecutor")
	@Transactional
	public void startDailyDraw(Integer drawId) {
		// TODO 天天抽奖开启抽奖
		try {
			/*1.按幸运值排序，抽取前十位，进行抽奖*/
			List<CatDailyDrawDetailResp> list = dailyDrawDetailRespDao.list(new CatDailyDrawDetailResp(drawId), "getTop10");
			if (list==null) {
				return;
			}
			//获取本轮抽奖设置信息
			CatDailyDrawHistory drawHistory = dailyDrawHistoryRepository.findById(drawId.longValue());
			//获取奖品信息
			CatDailyDrawPrizeInfo prizeInfoTemp = dailyDrawPrizeInfoRepository.findById(drawHistory.getPrizeId());
			
			CatDailyDrawPrizeInfo prizeInfo=new CatDailyDrawPrizeInfo();
			
			BeanUtils.copyProperties(prizeInfoTemp, prizeInfo);
			
			Map<String, Prize> map=new HashMap<>();
			
			List<Prize> collect = list.stream().map(obj->{
				return new Prize(obj.getPid(), 1, obj.getLuckyValue());
			}).collect(Collectors.toList());
			
			for (int i = 0; i < collect.size(); i++) {
				map.put(list.get(i).getPid(), collect.get(i));
			}
			
			List<CatDailyDrawResult> resultList=new ArrayList<>();
			//进行抽奖
			String pid=CalculateUtil.ratioExtract(collect);
			resultList.add(new CatDailyDrawResult(drawId.longValue(),pid,1,(int)map.get(pid).getPrizeWeight(),0,new Date()));
			if (prizeInfo.getPrizeNum()>1) {
				//删除已抽中的用户
				collect.remove(map.get(pid));
				StringBuffer buffer=new StringBuffer(pid);
				for (int i = 1; i < prizeInfo.getPrizeNum(); i++) {
					String extract = CalculateUtil.ratioExtract(collect);
					buffer.append(","+extract);
					resultList.add(new CatDailyDrawResult(drawId.longValue(),extract,1,(int)map.get(pid).getPrizeWeight(),0,new Date()));
				}
				pid=buffer.toString();
			}
			
			drawHistory.setDrawStatus(1);
			drawHistory.setDrawTime(new Date());
			drawHistory.setUpdateTime(new Date());
			drawHistory.setPid(pid);
			dailyDrawHistoryRepository.saveAndFlush(drawHistory);
			
			//记录到抽奖结果表中
			dailyDrawResultRepository.saveAll(resultList);
			dailyDrawResultRepository.flush();
			
			//通知抽奖用户开奖了
			//通过id获取devicetoken值
			try {
				List<String> tokenList = stringDao.list(new CatDailyDrawResult((long)drawId), "getDeviceToken");
				String ticker="你参与的活动已开奖";
				String title="开奖了";
				String text="你参与的一个抽奖活动正在开奖，请前往开奖";
				//通过devicetoken值通知用户开奖了
				UmengPushAPI.getInstance().sendAndroidListcast(ticker, title, text, tokenList);
			}catch(Exception e) {
				e.printStackTrace();
			}
			//如果奖品已下架则不再进入下一轮抽奖
			if (prizeInfo.getPrizeStatus()<=0) {
				return;
			}
			Date date = new Date();													
			//判断优惠券是否已失效，如果已失效则奖品也设置成下架状态
			if(prizeInfo.getPrizeStatus()!=-1 && prizeInfo.getEndTime().getTime()<date.getTime()) {
				prizeInfo.setPrizeStatus(-1);
				prizeInfo.setUpdateTime(new Date());
				dailyDrawPrizeInfoDao.update(prizeInfo, "updateStatus");
				return;
			}
			//开启下一轮抽奖
			int round = drawHistory.getRound()+1;
			Integer condition = prizeInfo.getCondition();
			CatDailyDrawHistory history=CatDailyDrawHistory.builder().prizeId(prizeInfo.getId()).round(round)
			.drawTotal(condition).drawStatus(0).drawNum(prizeInfo.getPrizeNum()).createTime(new Date()).build();
			dailyDrawHistoryRepository.saveAndFlush(history);
		} catch (Exception e) {
			log.error("开奖失败:"+e.getMessage());
			e.printStackTrace();
		}
	}
}
